using System;
using System.Collections.Generic;
using System.Drawing.Printing;
using System.Linq;
using System.Management;

namespace IppServer.Host.Printing
{
    /// <summary>
    /// 打印机过滤工具类
    /// 用于区分物理/网络打印机和虚拟打印机
    /// </summary>
    internal static class PrinterFilter
    {
        private static readonly string[] HardwarePortPrefixes =
        {
            "USB", "DOT4", "LPT", "COM", "IP_", "IPP", "TCP", "WSD", "CN", "BRN", "\\\\", "HPSTANDARDTCPPORT", "RNP", "LAN"
        };

        private static readonly string[] VirtualPortNames =
        {
            "FILE:", "PORTPROMPT:", "NUL:", "XPSPORT:", "SHRFAX:", "FAX:", "DOCUPRINT", "HPFAX", "SMARTPORT"
        };

        private static readonly string[] VirtualPrinterKeywords =
        {
            "PDF", "XPS", "FAX", "ONENOTE", "SNAGIT", "虚拟", "MICROSOFT PRINT"
        };

        /// <summary>
        /// 获取所有物理/网络打印机列表（排除虚拟打印机）
        /// </summary>
        public static List<string> GetPhysicalPrinters()
        {
            var filtered = new List<string>();
            var fallback = new List<string>();

            try
            {
                using (var searcher = new ManagementObjectSearcher("SELECT Name, PortName, Network, DriverName FROM Win32_Printer"))
                using (var results = searcher.Get())
                {
                    foreach (ManagementObject printer in results)
                    {
                        var name = (printer["Name"] as string)?.Trim();
                        if (string.IsNullOrEmpty(name))
                        {
                            continue;
                        }

                        fallback.Add(name);
                        if (IsPhysicalOrNetworkPrinter(printer))
                        {
                            filtered.Add(name);
                        }
                    }
                }
            }
            catch (Exception)
            {
                // 如果 WMI 查询失败，回退到 PrinterSettings.InstalledPrinters
                // 这种情况下无法区分虚拟打印机，返回全部打印机
            }

            if (filtered.Count == 0)
            {
                if (fallback.Count == 0)
                {
                    foreach (string printer in PrinterSettings.InstalledPrinters)
                    {
                        fallback.Add(printer);
                    }
                }
                return fallback.OrderBy(n => n, StringComparer.CurrentCultureIgnoreCase).ToList();
            }

            return filtered.OrderBy(n => n, StringComparer.CurrentCultureIgnoreCase).ToList();
        }

        /// <summary>
        /// 判断是否为物理或网络打印机
        /// </summary>
        public static bool IsPhysicalOrNetworkPrinter(ManagementBaseObject printer)
        {
            var port = (printer["PortName"] as string)?.Trim() ?? string.Empty;
            var name = (printer["Name"] as string)?.Trim() ?? string.Empty;
            var driver = (printer["DriverName"] as string)?.Trim() ?? string.Empty;
            var isNetwork = printer["Network"] is bool flag && flag;

            if (isNetwork)
            {
                return true;
            }

            if (string.IsNullOrEmpty(port))
            {
                return false;
            }

            var upperPort = port.ToUpperInvariant();
            var upperName = name.ToUpperInvariant();
            var upperDriver = driver.ToUpperInvariant();

            if (IsVirtualPort(upperPort))
            {
                return false;
            }

            if (ContainsVirtualKeyword(upperName) || ContainsVirtualKeyword(upperDriver))
            {
                return false;
            }

            return HardwarePortPrefixes.Any(prefix => upperPort.StartsWith(prefix, StringComparison.OrdinalIgnoreCase));
        }

        /// <summary>
        /// 判断端口是否为虚拟端口
        /// </summary>
        private static bool IsVirtualPort(string port)
        {
            foreach (var blocked in VirtualPortNames)
            {
                if (port.StartsWith(blocked, StringComparison.OrdinalIgnoreCase))
                {
                    return true;
                }
            }

            return false;
        }

        /// <summary>
        /// 判断是否包含虚拟打印机关键字
        /// </summary>
        private static bool ContainsVirtualKeyword(string source)
        {
            if (string.IsNullOrEmpty(source))
            {
                return false;
            }

            foreach (var keyword in VirtualPrinterKeywords)
            {
                if (source.IndexOf(keyword, StringComparison.OrdinalIgnoreCase) >= 0)
                {
                    return true;
                }
            }

            return false;
        }
    }
}

